/* 
 * File:   StorageAssignment.h
 * Author: lusitanio
 *
 * Created on 30 de Junho de 2011, 20:54
 */

#ifndef STORAGEASSIGNMENT_H
#define	STORAGEASSIGNMENT_H

#include <map>
#include <iostream>
#include <vector>
#include "GenericRow.h"

using namespace std;

class StorageAssignment : public AppData {
    // AppData variables
    int size_;
    char* str_;

    u_int32_t id_; // Identificação do Storage Assignment
    float ti_; // Tempo inicial
    float tf_; // Tempo final
    //map <float, u_int32_t> index_;
    vector<GenericRow> rows;

    float min;
    float max;

    int nbins;



public:

    StorageAssignment() : AppData(MSCOOP_DATA), size_(0), str_(NULL) {
        id_ = 0;
        ti_ = 0.0f;
        tf_ = 0.0f;
        min = NULL;
        max = NULL;
    }

    StorageAssignment(const StorageAssignment& data) : AppData(MSCOOP_DATA) {
        id_ = data.id_;
        ti_ = data.ti_;
        tf_ = data.tf_;
        rows = data.rows;
        min = data.min;
        max = data.max;
        nbins = data.nbins;
        size_ = data.size_;
        if (size_ > 0) {
            str_ = new char[size_];
            strcpy(str_, data.str_);
        } else str_ = NULL;
    }

    StorageAssignment(u_int32_t id, float ti, float tf, pair<float, float> limites, int nbins) : AppData(MSCOOP_DATA), size_(0), str_(NULL) {
        this->id_ = id;
        this->ti_ = ti;
        this->tf_ = tf;
        this->rows = *new vector<GenericRow > (nbins);
        this->min = limites.first;
        this->max = limites.second;
        this->nbins = nbins;

    }

    StorageAssignment & operator =(const StorageAssignment &data) {
        if (this == &data) {
            // avoid self-assignment
            return *this;
        } else {
            id_ = data.id_;
            ti_ = data.ti_;
            tf_ = data.tf_;
            rows = data.rows;
            min = data.min;
            max = data.max;
            nbins = data.nbins;
            size_ = data.size_;
            if (size_ > 0) {
                str_ = new char[size_];
                strcpy(str_, data.str_);
            } else str_ = NULL;
            return *this;
        }
    }

    void setId(u_int32_t id) {
        id_ = id;
    }

    u_int32_t getId() {
        return id_;
    }

    void setTi(float ti) {
        ti_ = ti;
    }

    float getTi() {
        return ti_;
    }

    void setTf(float tf) {
        tf_ = tf;
    }

    float getTf() {
        return tf_;
    }

    vector<GenericRow> getIntervals() {
        float value = this->min;
        float intervalo = (((this->max) - (this->min)) / this->nbins);
        printf("NBINS: %d Intervalo: %f\n", nbins, intervalo);
        vector<GenericRow> w_return = *new vector<GenericRow > (nbins);

        //        for(float i=min;i<=max;i+=intervalo){
        for (int pos = 0; pos < nbins; pos++) {
            GenericRow aux;
            if (pos == nbins - 1)
                aux = *new GenericRow(pos, value, this->max);
            else
                aux = *new GenericRow(pos, value, value + intervalo);
            aux.SetSaType();
            w_return.at(pos) = aux;
            value += intervalo;
        }
        w_return.at(nbins-1).SetFim(max);
        rows = *new vector<GenericRow > (w_return);
        return w_return;
    }

    void insertEntry(GenericRow entrada) {
        rows.at(entrada.GetPosicao()) = entrada;
    }

    void setEntry(int pos, int owner) {
        rows.at(pos).SetResponsavel(owner);
    }

    int returnOwner(float value) {
        vector<GenericRow>::iterator it;
        int w_return = 99999;
        for (it = rows.begin(); it < rows.end(); it++) {
            GenericRow aux = *it;
            if (aux.checkRange(value))
                w_return = aux.GetResponsavel();
        }
        if (w_return == 99999) {
            if (value <= min)
                w_return = rows[0].GetResponsavel();
            if (value >= max)
                w_return = rows[rows.size() - 1].GetResponsavel();
        }
        return w_return;
    }

    int returnOwnerPos(int pos) {
        return rows[pos].GetResponsavel();
    }

    int returnPosition(float value) {
        vector<GenericRow>::iterator it;
        int w_return = 99999;
        for (it = rows.begin(); it < rows.end(); it++) {
            GenericRow aux = *it;
            if (aux.checkRange(value))
                w_return = aux.GetPosicao();
        }
        return w_return;
    }

    virtual ~StorageAssignment() {
        if (str_ != NULL) delete []str_;
        //if (keys != NULL) delete []keys;
        //if (values != NULL) delete []values;
        //index_.clear();
    }

    char* str() {
        return str_;
    }

    virtual int size() const {
        //printf("sizeof(StorageAssignment): %d\n",sizeof(StorageAssignment));
        return AppData::size() + size_;
    }

    void set_string(const char* s) {
        if ((s == NULL) || (*s == 0))
            str_ = NULL, size_ = 0;
        else {
            size_ = strlen(s) + 1;
            str_ = new char[size_];
            assert(str_ != NULL);
            strcpy(str_, s);
        }
    }

    virtual AppData* copy() {
        return new StorageAssignment(*this);
    }

    float getMax() const {
        return max;
    }

    void setMax(float max) {
        this->max = max;
    }

    float getMin() const {
        return min;
    }

    void setMin(float min) {
        this->min = min;
    }

    vector<GenericRow> getRows() const {
        return rows;
    }

    void setRows(vector<GenericRow> rows) {
        this->rows = rows;
    }

    int getNbins() const {
        return nbins;
    }

    void print() {
        vector<GenericRow>::iterator it;
        GenericRow aux;
        puts("##### SA #####");
        printf("END MEMORIA: %d\n", this);
        printf("ID: %d\n", id_);
        printf("TI: %f TF: %f\n", ti_, tf_);
        for (it = rows.begin(); it < rows.end(); it++) {
            aux = *it;
            printf("[SA]Intervalo[%2.2f|%2.2f] -> Owner: %d\n", aux.GetInicio(), aux.GetFim(), aux.GetResponsavel());
        }
        // show content:
        //        for (it = index_.begin(); it != index_.end(); it++)
        //            // cout << (*it).first << " => " << (*it).second << endl;
        //            printf("[SA]Valor: %f -> Owner: %d\n", (*it).first, (*it).second);
    }

};

#endif	/* STORAGEASSIGNMENT_H */
